/*!
 * \file CplexDesigualdades.h
 *
 * \date Aug 14, 2014
 * \author correa
 */
#ifndef CPLEXDESIGUALDADES_H_
#define CPLEXDESIGUALDADES_H_

using namespace std;

#include <IntValueArray.h>
#include <Desigualdad.h>
#include <MapaRepresentaciones.h>
#include <ilcplex/ilocplex.h>
#include <ilcplex/ilocplexi.h>

class RangeDesigualdad : public Desigualdad
{
protected:
	IloNumVarArray& 	_x;
	IloRange&			_range;
	RangeDesigualdad(IloNumVarArray& x, IloRange& range, int nv, int nx);
	RangeDesigualdad(IloNumVarArray& x, IloRange& range);
public:
	RangeDesigualdad(const RangeDesigualdad& otra);
	RangeDesigualdad(const RangeDesigualdad&& otra);
	virtual ~RangeDesigualdad();

	RangeDesigualdad& operator=(RangeDesigualdad const& otra);
	RangeDesigualdad& operator=(RangeDesigualdad&& otra);

	virtual void setCoeficiente(int i, int coef);
	virtual int getRHS() const;
	virtual void setRHS(int valor);
	void print();
};

class CplexDesigualdad : public IloRange, public RangeDesigualdad
{
protected:
	CplexDesigualdad(IloNumVarArray& x, int nv, int nx);
public:
	CplexDesigualdad(IloNumVarArray& x);
	CplexDesigualdad(const CplexDesigualdad& otra);
	virtual ~CplexDesigualdad();
};

class CplexRepDesigualdad;

class RepRangeDesigualdad : public RangeDesigualdad
{
	friend class CplexRepDesigualdad;

	MatrixOfRepresentaciones& 	_mapa;
	ArrayOfRepresentaciones& 	_array;

	RepRangeDesigualdad(int rep, IloNumVarArray& x, IloRange& range, MatrixOfRepresentaciones& mapa, ArrayOfRepresentaciones& array, bool dummy);

protected:
	int							_rep;

	RepRangeDesigualdad(int rep, IloNumVarArray& x, IloRange& range, MatrixOfRepresentaciones& mapa, ArrayOfRepresentaciones& array);

public:
	RepRangeDesigualdad(const RepRangeDesigualdad& otra);
	RepRangeDesigualdad(const RepRangeDesigualdad&& otra);
	virtual ~RepRangeDesigualdad() {};

	RepRangeDesigualdad& operator=(RepRangeDesigualdad const& otra);  // copy assignment
	RepRangeDesigualdad& operator=(RepRangeDesigualdad&& otra);// move assignment

	void setCoeficiente(int i, int coef);
	int getCoeficiente(int i);
	const IntValueArray& getCoeficientes();
	virtual int getRHS() const { cout << "RepRangeDesigualdad: getRHS not allowed." << endl; throw(-1); };
	virtual void setRHS(int valor) { cout << "RepRangeDesigualdad: setRHS not allowed." << endl; throw(-1); };
	virtual void setAsRank() { cout << "RepRangeDesigualdad: setAsRank not allowed." << endl; throw(-1); };
	virtual void setAsNotRank() { cout << "RepRangeDesigualdad: setAsNotRank not allowed." << endl; throw(-1); };
	virtual bool isRank() { cout << "RepRangeDesigualdad: isRank not allowed." << endl; throw(-1); };
	void print();
};

class CplexSubRepDesigualdad : public IloRange, public RepRangeDesigualdad
{
public:
	CplexSubRepDesigualdad(int rep, IloNumVarArray& x, MatrixOfRepresentaciones& mapa, ArrayOfRepresentaciones& array);
	CplexSubRepDesigualdad(const CplexSubRepDesigualdad& otra);
	~CplexSubRepDesigualdad();

	int getRHS() const;
	void setRHS(int valor);
	void setAsRank() { Desigualdad::setAsRank(); };
	void setAsNotRank() { Desigualdad::setAsNotRank(); };
	bool isRank() { return Desigualdad::isRank(); };
	void print();
};

class CplexRepDesigualdad : public IloRange, public DesigualdadArray<RepRangeDesigualdad>
{
	IloNumVarArray& 			_x;
	MatrixOfRepresentaciones& 	_mapa;
	ArrayOfRepresentaciones& 	_array;

public:
	CplexRepDesigualdad(IloNumVarArray& x, MatrixOfRepresentaciones& mapa, ArrayOfRepresentaciones& array);
	virtual ~CplexRepDesigualdad() {};
    RepRangeDesigualdad& operator[](int i);
	int getRHS() const;
	void setRHS(int valor);
	void print();
};

#endif /* CPLEXDESIGUALDADES_H_ */
